package edu.uj.petri.commands;

import java.io.Serializable;
import java.util.ResourceBundle;

/**
 * Command is a standalone object able to be executed without being given any 
 * arguments. Thus, all required references should be kept inside it. Command 
 * is also able to be undone so it needs to store some special {@link Memento 
 * Mementos} of objects it operates on.
 *
 * @author Piotrek
 */
public abstract class Command implements Serializable {
    
    /**
     * states whether command should be able to be undone/redone. False by
     * default.
     */
    private boolean executeAndForget=false;
    
    public Command() {
    }
    
    public Command(boolean executeAndForget) {
        this.executeAndForget = executeAndForget;
    }
    
    /**
     * returns human-readable, clear description what the command actually does
     */
    public abstract String toString();

    /**
     * executes command
     */
    abstract void execute();

    /** rollbacks command */
    abstract void undo();

    /** returns true when this command can be combined (joined) with another */
    abstract boolean canBeCombined(Command c);

    /** adds another command to this. As result, this command should work
     * as two commands.
     * @throw IllegalArgumentException when called on command, which cannot
     * be combined with command given in argument
     */
    void combine(Command c) {
        throw new IllegalArgumentException(ResourceBundle.getBundle("edu/uj/petri/messages").getString(
                "cannot_be_combined"));
    }
    
    /**
     * returns true when command should be only executed once and not remembered
     * on command stack (thus, not undone/redone). Commands showing dialog
     * windows and similar are examples of "execute and forget" commands
     * (there is no sense in showing dialog again when redoing the command).
     * For most commands, this will return false.
     */
    final boolean isExecuteAndForget() {
        return executeAndForget;
    }
}
